<template>
  <div ref="threeContainer" id="threeContainer"></div>
</template>

<script setup>
  import * as THREE from "three"
  import { onMounted } from "@vue/runtime-core"
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
  import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
  import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
  import { useDebounceThrottle } from '@/utils/useDebounceThrottle';
  import * as TWEEN from "three/examples/jsm/libs/tween.module.js"
  // 效果制作器
  import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
  // 渲染通道
  import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
  // 发光描边OutlinePass
  import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
  import { OutputPass } from "three/addons/postprocessing/OutputPass.js";
  import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
  import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"
  import Stats from 'stats.js';

  const threeContainer = ref(null)

  onMounted(() => {
    // 创建场景
    const scene = new THREE.Scene()
    // 改变背景颜色
    // scene.background = new THREE.Color('#fff')
    // 添加背景图片
    // const urls = [
    //   '1.png', '1.png', '1.png', '1.png', '1.png', '1.png'
    // ]
    // scene.background = new THREE.CubeTextureLoader().load(urls)

    // 创建纹理
    // const texture = new THREE.TextureLoader().load('1.png')

    // 添加雾效
    // scene.fog = new THREE.Fog(0xffffff, 5, 15)

    // 创建相机
    const camera = window.camera = new THREE.PerspectiveCamera()
    camera.position.y = 3
    camera.position.z = 10
    
    // // 创建立方体
    // const geometry = new THREE.BoxGeometry(1, 1, 1)
    // // const material = new THREE.MeshBasicMaterial({ 
    // //   // color: 0x0099ff,
    // //   map: texture,
    // // })
    // const material = new THREE.MeshPhongMaterial({ 
    //   color: 0x0099ff,
    //   // map: texture,
    //   shininess: 30,
    // })

    // // 网格
    // const cube = new THREE.Mesh(geometry, material)
    // cube.position.set(0, 0.5, 0)
    // // 物体接受光源
    // cube.receiveShadow = true
    // // 投射光源
    // cube.castShadow = true
    // // 添加 三维向量
    // cube.position.add(vector)
    // scene.add(cube)

    // 添加灯光效果
    // 环境光
    const light = new THREE.AmbientLight(0xffffff, 5)
    scene.add(light)
    // 点光源
    // const pointLight = new THREE.PointLight(0xffffff, 100, 100)
    // pointLight.position.set(5, 3, 5)
    // pointLight.castShadow = true
    // scene.add(pointLight)

    // 创建地面
    const meshfloor = new THREE.Mesh(
      new THREE.PlaneGeometry(10, 10),
      new THREE.MeshPhongMaterial({
        color: 0x1b5e20,
      })
    )
    meshfloor.rotation.x -= Math.PI / 2
    // 地面接受光源
    meshfloor.receiveShadow = true
    scene.add(meshfloor)

    // 添加网格地面
    const gridHelper = new THREE.GridHelper(10, 10)
    scene.add(gridHelper)

    // 创建渲染器
    const renderer = new THREE.WebGLRenderer()
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.shadowMap.enabled = true
    // 将渲染器添加到页面
    document.getElementById("threeContainer").appendChild(renderer.domElement);

    // 添加轨道控制器
    const controls = new OrbitControls(camera, renderer.domElement)
    // 自动旋转 整体
    // controls.autoRotate = true;
    // controls.autoRotateSpeed = 0.5;
    // 对轨道控制器改变时 监听
    controls.addEventListener("change", () => {
      // renderer.render(scene, camera);
    })

    // // 添加坐标轴
    // const axesHelper = new THREE.AxesHelper(5) // 红x 绿y 蓝z
    // axesHelper.position.set(0, 0, 0)
    // scene.add(axesHelper)

    // 切换文字
    let isNext = ref(true)
    let mesh;
    // 创建canvas
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    
    // #region
    // // 绘制文字
    // let drawCont = (value) => {
    //   scene.remove(mesh)
    //   ctx.clearRect(0, 0, canvas.width, canvas.height)
    //   ctx.font = '16px Arial';
    //   ctx.fillStyle = '#ff0000';
    //   ctx.fillText('扬尘噪声检测', 0, 16)
      
    //   if(value) {
    //     ctx.fillText('PM2.5: 158', 0, 32)
    //     ctx.fillText('Pm10: 158', 0, 48)
    //     ctx.fillText('tsp: 270', 0, 64)
    //   } else {
    //     ctx.fillText('tsp: 270', 0, 32)
    //     ctx.fillText('PM2.5: 158', 0, 48)
    //     ctx.fillText('Pm10: 158', 0, 64)
    //   }
    //   let url = canvas.toDataURL('image/png')
    //   let material = new THREE.MeshBasicMaterial({
    //     map: new THREE.TextureLoader().load(url),
    //     // side: THREE.DoubleSide,
    //     transparent: true,
    //   })
    //   let geometry = new THREE.PlaneGeometry(2, 2)
    //   mesh = new THREE.Mesh(geometry, material);
    //   mesh.position.set(0, -0.3, 0.4)
    //   isNext.value = !isNext.value
    // }

    // drawCont(isNext.value)
    // setInterval(() => {
    //   // drawCont(isNext.value)
    //   // scene.add(mesh)
    // }, 3000);
    // #endregion

    // 移入模型高亮
    const composer = new EffectComposer(renderer);
    const renderPass = new RenderPass(scene, camera);
    composer.addPass(renderPass); // 特效渲染
    const outputPass = new OutputPass();
    composer.addPass(outputPass);
    const outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene,camera);
    outlinePass.pulsePeriod = 0; // 数值越大，规律越慢
    outlinePass.visibleEdgeColor.set(0x00ffff); // 高光颜色
    outlinePass.hiddenEdgeColor.set(0x00ff00); // 阴影颜色
    outlinePass.usePatternTexture = false; // 是否使用纹理覆盖
    outlinePass.edgeStrength = 1; // 高光边缘强度
    outlinePass.edgeGlow = 1; // 边缘微光强度
    outlinePass.edgeThickness = 1; // 高光厚度
    outlinePass.clear = true
    composer.addPass(outlinePass); // 加入高管特效
    
    let effectFXAA = new ShaderPass(FXAAShader)
    effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)
    effectFXAA.renderToScreen = true
    composer.addPass(effectFXAA)
                        
    const outlineObj = (model) => {
      if(model) {
        outlinePass.selectedObjects = model;
      }
    }
    
    let gltfBorder = ref(null)
    let glb1 = ref(null)
    let model = null
    const loader = new GLTFLoader()
    const dracoLoader = new DRACOLoader()
    // 设置draco路径
    dracoLoader.setDecoderPath('/draco/');
    // 使用js方式解压
    dracoLoader.setDecoderConfig({ type: "js" });
    // 初始化_initDecoder 解码器
    dracoLoader.preload();
    // 设置gltf加载器draco解码器
    loader.setDRACOLoader(dracoLoader);
    // 创建gltf实例
    loader.load('/Mars/1.glb', (gltf) => {
      gltf.scene.scale.set(0.0002, 0.0002, 0.0002)
      gltf.scene.position.set(0, 0.5, 0)
      gltf.scene.rotation.set(0, -0.9, 0)
      gltf.scene.name = 'glb1'
      scene.add(gltf.scene)
      // scene.add(mesh)
      glb1 = gltf.scene
      model = gltf
      gltfBorder = new THREE.BoxHelper(gltf.scene, 0xffff00 );
      gltfBorder.visible = false
      scene.add(gltfBorder)
    }, undefined, (error) => {
      console.log(error)
    })
    
    const stats = new Stats();
    stats.showPanel(0); // 显示面板 0: fps, 1: ms, 2: mb, 3+: custom
    document.body.appendChild(stats.dom);

    // 射线投射器
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();
    const onMousemove = (event) => {
      // 计算鼠标点击位置
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
      // 更新射线投射方向
      raycaster.setFromCamera(mouse, camera);
      if(!glb1.visible) return;
      // 计算射线投射的物体交点
      const intersects = raycaster.intersectObjects([glb1], true);
      if (!intersects.length) {
        gltfBorder.visible = false
        return;
      }
      
      intersects.find((item) => {
        if(item.object.name) {
        // console.log('item:', item.object)
        }
      })

      let findObj = null
      const findClickModel = (object) => {
        object._isSelect = false
        if (object.name.includes("组6821")) {
          object._isSelect = true
          findObj = object
          return;
        }
        if (object.parent) {
          findClickModel(object.parent);
        }
      };
      // 点击到模型时的处理
      const selectedObject = intersects[0].object || {};
      // 检查点击的对象是否为模型
      if (selectedObject.name) {
        findClickModel(selectedObject)
        // gltfBorder.visible = true
        if(findObj && findObj._isSelect) {
          findObj._isSelect = false 
          outlineObj([findObj])
        } else {
          findObj._isSelect = true
          outlinePass.enabled = false
        }
      }
    }
    // 鼠标点击事件监听器
    window.addEventListener('mousemove', onMousemove, false);

    // 创建星星的材质
    const starGeometry = new THREE.SphereGeometry(0.25, 20, 20);
    const starMaterial = new THREE.MeshBasicMaterial({ size: 0.1, color: 0xffffff });
    // 创建并添加1000颗星星
    for (let i = 0; i < 1300; i++) {
      const star = new THREE.Mesh(starGeometry, starMaterial);
      // 随机位置
      star.position.x = THREE.MathUtils.randFloatSpread(1000);
      star.position.y = THREE.MathUtils.randFloatSpread(1000);
      star.position.z = THREE.MathUtils.randFloatSpread(1000);
      // 添加到场景
      scene.add(star);
    }

    // 添加环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 1)
    // scene.add(ambientLight)
    // 添加平行光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1)
    directionalLight.position.set(0, 10, 10)
    directionalLight.castShadow = true
    // scene.add(directionalLight)

    const animate = () => {
      requestAnimationFrame(animate)
      // cube.rotation.x += 0.01;
      // cube.rotation.y += 0.01;
      controls.update()
      renderer.render(scene, camera)
      if(composer) {
        composer.render();
      }
      stats.update()
    }
    animate()
    // 渲染
    // renderer.render(scene, camera);
    // 监听画面变化，更新渲染画面
    window.addEventListener("resize", () => {
      // 更新摄像头
      camera.aspect = window.innerWidth / window.innerHeight;
      //   更新摄像机的投影矩阵
      camera.updateProjectionMatrix();
      //   更新渲染器
      renderer.setSize(window.innerWidth, window.innerHeight);
      //   设置渲染器的像素比
      renderer.setPixelRatio(window.devicePixelRatio);
    });
  })
</script>

<style scoped>
  #threeContainer {
    width: 100%;
    height: 100%;
  }
</style>
